module rd0 #(
    parameter
        FRAME_ROW     = 16'd480, // 一帧的行数
        FRAME_LINE    = 16'd640, // 一帧的列数，16bit为一个单位
        RD0_BURST_LEN = 16'd160, // wr0_fifo一次突发要突发的长度，
        RD0_THRESHOLD = 16'd640  // wr0驱动ddr写的阈值——1行数据
)(
    input                   clk                 ,
    input                   rst_n               ,
    // fifo 接口
    input                   rd0_wr_clk          ,
    input                   rd0_rd_clk          ,
    input                   rd0_rd_en           ,
    output      [15:0]      rd0_16bit_dout      ,
    output      [10:0]      rd0_11bit_rd_cnt    ,
    // ddr3 接口
    input                   output_fifo_wr_en   , // 输出fifo写入使能
    input       [127:0]     rd_data             , // ddr 读取的数据，接输出fifo
    input                   rd_done             , // 一次写完成标志
    output reg  [ 24:0]     begin_addr          , // ddr 读写开始地址
    output                  rw                  , // ddr 读写标志，1读 0写
    output      [ 15:0]     burst_data_len      , // 突发长度
    output reg              exc                   // 执行标志
);
// 参数定义-------------------------
reg  [15:0] row_cnt;
reg  [ 1:0] mask_switch;
reg  [15:0] rd0_wr_data_cnt; // 4x16bit一个数据
reg  [15:0] rd0_wr_row_cnt;
reg         rd0_wr_data_switch;
wire [63:0] rd0_64bit_din;
wire        rd0_wr_en;
// 前置操作-------------------------
// 已读取的行，行计数
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        row_cnt <= 16'd0;
    else if((row_cnt == FRAME_ROW - 16'd1) && rd_done)             // 写满了一帧，计数复位
        row_cnt <= 16'd0;
    else if(rd_done)
        row_cnt <= row_cnt + 16'd1;
    else 
        row_cnt <= row_cnt;
end

// 对已经写入rd0_fifo的数据进行分析——对数据进行拆解，根据帧数读取高位或低位
always @(posedge clk or negedge rst_n) begin // 已写入rd0 fifo行中的数目计数，不可以用fifo的cnt计数，因为可能该fifo在同时读写中
    if(~rst_n)
        rd0_wr_data_cnt <= 16'd0;
    else if(rd0_wr_data_cnt == RD0_BURST_LEN - 16'd1)
        rd0_wr_data_cnt <= 16'd0;
    else if(rd0_wr_en)
        rd0_wr_data_cnt <= rd0_wr_data_cnt + 16'd1;
    else ;
end

// 已写入rd0 fifo的行计数
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        rd0_wr_row_cnt <= 1'd0;
    else if((rd0_wr_row_cnt == FRAME_ROW - 16'd1) && (rd0_wr_data_cnt == RD0_BURST_LEN - 16'd1))
        rd0_wr_row_cnt <= 16'd0;
    else if(rd0_wr_data_cnt == RD0_BURST_LEN - 16'd1)
        rd0_wr_row_cnt <= rd0_wr_row_cnt + 16'd1;
    else ;
end

//读数标志转换
always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
        rd0_wr_data_switch <= 1'd0;
    else if((rd0_wr_row_cnt == FRAME_ROW - 16'd1) && (rd0_wr_data_cnt == RD0_BURST_LEN - 16'd1)) // 一帧写完
        rd0_wr_data_switch <= ~rd0_wr_data_switch;
    else ;
end

// 信号输出-------------------------

// rd_data
assign rd0_64bit_din = (rd0_wr_data_switch) ? rd_data[127:64] : rd_data[63:0];

// begin_addr
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        begin_addr <= 25'd0;
    else if(rd_done && (row_cnt == FRAME_ROW - 16'd1)) // 写满了一帧，地址复位
        begin_addr <= 25'd0;
    else if(rd_done)           
        begin_addr <= begin_addr + (FRAME_LINE << 1);
    else 
        begin_addr <= begin_addr;
end

// rw
assign rw               = 1'd1;           // 读操作

// burst_data_len
assign burst_data_len   = RD0_BURST_LEN;  

// exc
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        exc <= 1'd0;
    else if(rd0_11bit_rd_cnt < RD0_THRESHOLD)
        exc <= 1'd1;
    else 
        exc <= 1'd0;
end

// rd0_fifo-------------------------
assign rd0_wr_en = output_fifo_wr_en;
rd0_fifo_512x64_2048x16 u_rd0_fifo (
    .rst            (~rst_n             ),  // input wire rst
    .wr_clk         (rd0_wr_clk         ),  // input wire wr_clk
    .rd_clk         (rd0_rd_clk         ),  // input wire rd_clk
    .din            (rd0_64bit_din      ),  // input wire [63 : 0] din
    .wr_en          (rd0_wr_en          ),  // input wire wr_en
    .rd_en          (rd0_rd_en          ),  // input wire rd_en
    .dout           (rd0_16bit_dout     ),  // output wire [15 : 0] dout
    .full           (                   ),  // output wire full
    .empty          (                   ),  // output wire empty
    .rd_data_count  (rd0_11bit_rd_cnt   ),  // output wire [10 : 0] rd_data_count
    .wr_rst_busy    (                   ),  // output wire wr_rst_busy
    .rd_rst_busy    (                   )   // output wire rd_rst_busy
);
endmodule